﻿#include "FITKSEASubSysBeam.h"
#include "FITKAcousticsDiscNodeList.h"
#include "FITKAcousticsSEAModel.h"
#include "FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbstractSpectra.h"
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Kernel/FITKCore/FITKVec3DAlg.h"
#include "FITK_Interface/FITKInterfaceModel/FITKCoordinateSystem.h"

namespace Acoustics
{
    FITKAbstractSEASubSys::SEASubSysType Acoustics::FITKSEASubSysBeam::getSEASubSysType()
    {
        return FITKAbstractSEASubSys::SEASubSysType::SEABeam;
    }

    int FITKSEASubSysBeam::getFlexureXSpectraID()
    {
        return _flexureXSpectraID;
    }

    FITKAcousticsAbstractSpectra * FITKSEASubSysBeam::getFlexureXSpectra()
    {
        return FITKDATAREPO->getTDataByID<FITKAcousticsAbstractSpectra>(_flexureXSpectraID);
    }

    void FITKSEASubSysBeam::setFlexureXSpectraID(int id)
    {
        _flexureXSpectraID = id;
    }

    int FITKSEASubSysBeam::getFlexureYSpectraID()
    {
        return _flexureYSpectraID;
    }

    FITKAcousticsAbstractSpectra * FITKSEASubSysBeam::getFlexureYSpectra()
    {
        return FITKDATAREPO->getTDataByID<FITKAcousticsAbstractSpectra>(_flexureYSpectraID);
    }

    void FITKSEASubSysBeam::setFlexureYSpectraID(int id)
    {
        _flexureYSpectraID = id;
    }

    int FITKSEASubSysBeam::getExtensionZSpectraID()
    {
        return _extensionZSpectraID;
    }

    FITKAcousticsAbstractSpectra * FITKSEASubSysBeam::getExtensionZSpectra()
    {
        return FITKDATAREPO->getTDataByID<FITKAcousticsAbstractSpectra>(_extensionZSpectraID);
    }

    void FITKSEASubSysBeam::setExtensionZSpectraID(int id)
    {
        _extensionZSpectraID = id;
    }

    int FITKSEASubSysBeam::getTorsionZZSpectraID()
    {
        return _torsionZZSpectraID;
    }

    FITKAcousticsAbstractSpectra * FITKSEASubSysBeam::getTorsionZZSpectra()
    {
        return FITKDATAREPO->getTDataByID<FITKAcousticsAbstractSpectra>(_torsionZZSpectraID);
    }

    void FITKSEASubSysBeam::setTorsionZZSpectraID(int id)
    {
        _torsionZZSpectraID = id;
    }

    bool FITKSEASubSysBeam::updateCoordinate()
    {
        if (nullptr == _coordinate) return false;
        //子系统至少三个点
        QList<int> nodeIDs = this->getNodeIDs();
        if (nodeIDs.size() < 3) return false;
        //声学sea模型节点获取
        FITKAcousticsDiscNodeList* nodes = FITKAcousticsDiscModel::GetDiscModelFromFrame()->getNodes();
        if (nodes == nullptr) return false;

        Core::FITKNode* O1 = nodes->getNodeByID(nodeIDs[0]);
        Core::FITKNode* O2 = nodes->getNodeByID(nodeIDs[1]);
        Core::FITKNode* O = nodes->getNodeByID(nodeIDs.last());
        if (O1 == nullptr || O2 == nullptr || O == nullptr) return false;
        //z轴方向
        Core::FITKVec3D zDir = Core::Subtract(*O2, *O1);
        Core::FITKVec3D D2o = Core::Subtract(*O, *O2);
        //y轴
        Core::FITKVec3D yDir = Core::CrossProduct(zDir, D2o);
        //x轴
        Core::FITKVec3D xDir = Core::CrossProduct(yDir, zDir);
        //异常判断
        if (xDir.getNorm() < 1e-6 || yDir.getNorm() < 1e-6) return false;
        //保存坐标
        double coor[3] = { 0,0,0 };
        O1->getCoor(coor);
        _coordinate->setOrigin(coor[0], coor[1], coor[2]);
        _coordinate->setPoint1(coor[0] + xDir.x(), coor[1] + xDir.y(), coor[2] + xDir.z());
        _coordinate->setPoint1(coor[0] + yDir.x(), coor[1] + yDir.y(), coor[2] + yDir.z());

        return true;
        
    }

    bool FITKSEASubSysBeam::getConnectionLocationBySegment(int index, double percentage, double* location)
    {
        if (!location) return false;
        //获取节点id链表
        QList<int> nodeIDs = this->getNodeIDs();
        if (index + 3 > nodeIDs.size()) return false;
        //获取梁单元的两个节点ID
        int node1ID = nodeIDs.at(index);
        int node2ID = nodeIDs.at(index + 1);
        //获取梁单元的两个点的数据
        FITKAcousticsDiscNodeList* nodes = FITKAcousticsDiscModel::GetDiscModelFromFrame()->getNodes();
        if (nodes == nullptr) return false;
        Core::FITKNode* node1Data = nodes->getNodeByID(node1ID);
        Core::FITKNode* node2Data = nodes->getNodeByID(node2ID);
        if (!node1Data || !node2Data) return false;
        //获取两个点的位置
        double node1Location[3]{ 0,0,0 }, node2Location[3]{ 0,0,0 };
        node1Data->getCoor(node1Location);
        node2Data->getCoor(node2Location);
        //计算连接位置的占比
        location[0] = (node2Location[0] - node1Location[0]) * percentage + node1Location[0];
        location[1] = (node2Location[1] - node1Location[1]) * percentage + node1Location[1];
        location[2] = (node2Location[2] - node1Location[2]) * percentage + node1Location[2];
        return true;
    }

    bool FITKSEASubSysBeam::getSegmentByConnectionLocation(double* location, int& index, double& percentage)
    {
        if (!location) return false;
        FITKAcousticsDiscNodeList* nodes = FITKAcousticsDiscModel::GetDiscModelFromFrame()->getNodes();
        if (nodes == nullptr) return false;
        Core::FITKNode nodeLocation(0, location);
        //获取节点id链表
        QList<int> nodeIDs = this->getNodeIDs();
        for (int i = 0; i < nodeIDs.size() - 2; ++i)
        {
            int node1ID = nodeIDs.at(index);
            int node2ID = nodeIDs.at(index + 1);
            Core::FITKNode* node1Data = nodes->getNodeByID(node1ID);
            Core::FITKNode* node2Data = nodes->getNodeByID(node2ID);
            if (!node1Data || !node2Data) continue;
            Core::FITKNode node1 = *node1Data;
            Core::FITKNode node2 = *node2Data;
            double length = Core::Distance(node1, node2);
            double segment1 = Core::Distance(node1, nodeLocation);
            double segment2 = Core::Distance(nodeLocation, node2);
            if (fabs(length - segment1 - segment2) > 1e-15) continue;
            index = i;
            percentage = segment1 / length;
            return true;
        }
        return false;
    }
}



